﻿#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

//指针数组：用来存放指针的数组
//int main()
//{
//	int arr1[] = { 1,2,3,4,5,6 };
//	int arr2[] = { 2,3,4,5,6,7 };
//	int arr3[] = { 3,4,5,6,7,8 };
//	//数组名是数组首元素的地址，类型是int*的，就可以存放在arr数组中
//	int* arr[3] = { arr1,arr2,arr3 };
//	int i = 0;
//	for (i = 0; i < 3; i++)
//	{
//		int j = 0;
//		for (j = 0; j < 6; j++)
//		{
//			printf("%d ", arr[i][j]);
//		}
//		printf("\n");
//	}
//	return 0;
//}

//int main()
//{
//	char ch = 'w';
//	char* p = &ch;
//	printf("%c\n", ch);
//	printf("%c\n",*p);
//	*p = 'm';
//	printf("%c\n", ch);
//	printf("%c\n", *p);
//	return 0;
//}

//int main()
//{
//	//int a = 20;
//	//a = 200;
//	//2=3//err常量不能改变
//
//	const char* p = "hello world";// "hello world"是常量字符数组，在前面加上const体现，也可省略
//	//只把 "hello world"的首地址放到了p中
//	printf("%c", *p);//h
//	//*p='w'//err
//	const char* p1 = "yes";
//	p = &p1;
//	
//	return 0;
//}


//#include<string.h>
//int main()
//{
//	const char* p = "hello world";
//	printf("%s\n", p);
//	printf("%s\n", "hello world");
//
//	size_t len = strlen(p);//strlen()返回值是无符号整型用size_t
//	size_t i = 0;
//	for (i = 0; i < len; i++)
//	{
//		printf("%c", *(p + i));//从首地址开始依次向后访问地址
//	}
//	return 0;
//}


//int main()
//{
//	char str1[] = "hello world";
//	char str2[] = "hello world";
//	const char* str3 = "hello world";
//	const char* str4 = "hello world";
//	if (str1 == str2)
//		printf("str1 and str2 are same\n");
//	else
//		printf("str1 and str2 are not same\n");//√、
//	//用相同的字符串常量去初始化不同的数组会开辟不同的内存块
//	//所以str1、str2指向的不是同一块内存
//	if(str3==str4)
//		printf("str3 and str4 are same\n");//√
//	else
//		printf("str3 and str4 are not same\n");
//	//str3、str4指向的是一个同样的常量字符串，c/c++会把常量字符串存放到一个单独的一个内存区域
//	//所以str3、str4指向的是同一块内存
//	return 0;
//}


//int main()
//{
//	//int* ptr;//整型指针变量
//	//char arr[5];
//	//char(*p)[5] = &arr;
//	//p是数组指针变量
//	//char(*)[5]是数组指针类型
//	
//	char* arr1[5];
//	char* (*p)[5] = &arr1;
//	return 0;
//}


//int main()
//{
//	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//	int(*p)[10] = &arr;
//	int len = sizeof(arr) / sizeof(arr[0]);
//	int i = 0;
//	for (i = 0; i < len; i++)
//	{
//		printf("%d ", (*p)[i]);//&arr和p的类型是一样的
//		//          ==(*&arr)[i]
//		//          ==arr[i]
//	}
//	return 0;
//}

//void test(int arr[3][5], int r, int c)
//{
//	int i = 0, j = 0;
//	for (i = 0; i < 3; i++)
//	{
//		for (j = 0; j < 5; j++)
//		{
//			printf("%d ", arr[i][j]);
//		}
//		printf("\n");
//	}
//}
//int main()
//{
//	int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };
//	test(arr, 3, 5);
//	return 0;
//}
//
//二维数组传参本质上也是传递了地址，传递的是第一⾏这个一维数组的地址
//第⼀⾏的⼀维数组的类型就是 int [5] ，所以第⼀⾏的地址的类型就是数组指针类型 int(*)[5] 
//
//void test(int(*p)[5], int r, int c)
//{
//	int i = 0, j = 0;
//	for (i = 0; i < 3; i++)
//	{
//		for (j = 0; j < 5; j++)
//		{
//			printf("%d ", *(*(p + i)+j));
//		}
//		printf("\n");
//	}
//}
//int main()
//{
//	int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };
//	test(arr, 3, 5);
//	return 0;
//}

//int main()
//{
//	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//	int i = 0;
//	for (i = 0; i < 10; i++)
//	{
//		//printf("%d ", arr[i]);
//		printf("%d ", *(arr+i));
//		//arr是首元素的地址
//	}
//	return 0;
//}


//int add(int a, int b)
//{
//	return a + b;
//}
//int main()
//{
//	//int (*p)(int, int) = &add;
//	int (*p)(int, int) = add;
//
//	int x = 10;
//	int y = 20;
//	int z = add(x, y);
//	printf("%d\n", z);
//	printf("%p\n", add);
//	printf("%p\n", &add);
//	//&函数名和函数名都表示函数的地址
//
//	return 0;
//}


//int test(char* p)
//{
//	return NULL;
//}
//int main()
//{
//	int(*pt1)(char*) = test;
//	int(*pt2)(char* p) = &test;//p可以忽略不写
//	
//	int arr[8] = { 0 };
//	int(*pa)[8] = &arr;
//	return 0;
//}

//int add(int a, int b)
//{
//	return a + b;
//}
//int main()
//{
//	int (*pa1)(int, int) = &add;
//	int (*pa2)(int, int) = add;
//	int (*pa3)(int, int) = add;
//
//	int r1 = (*pa1)(3, 7);
//	int r2 = (*pa2)(3, 7);
//	int r3 = add(3, 7);
//
//	printf("%d\n", r1);
//	printf("%d\n", r2);
//	printf("%d\n", r3);
//	printf("%d\n", (*pa3)(3, 7));
//	printf("%d\n", pa3(3, 7));//*没有意义，可写可不写，多写几个也不会有问题
//
//	return 0;
//}


//int main()
//{
//	(*(void(*)())0)();
//	//1.将0强制类型转化为void(*)()类型的函数指针
//	//2.调用0地址处放的这个函数
//
//	return 0;
//}


void(*signal(int, void(*)(int)))(int);
//函数声明，声明的函数名为：signal
//signal有两个参数，一个参数的类型是int
// 第二个参数的类型是void(*)(int)的函数指针类型，该指针可以指向一个函数，指向的函数参数类型是int，返回类型是void
// signal函数的返回类型是voi(*)(int)的函数指针，该指针可以指向一个函数，指向的函数参数类型是int，返回类型是void
//void(*)(int) signal(int, void(*)(int)//err,好理解，但不支持这种写法


//typedef unsigned int uint;
//typedef int* pint;
//int main()
//{
//	unsigned int a;
//	uint b;
//
//	int* p1 = NULL;
//	pint* p2 = NULL;
//
//	return 0;
//}


//数组指针
//typedef int(*parr_t)[5];
//int main()
//{
//	int arr[5] = { 0 };
//	int(*p)[5] = &arr;
//	//int(*)[5]是数组指针类型
//	parr_t p2 = arr;
//	return 0;
//}


//函数指针
//void test(char* a)
//{
//
//}
//typedef void(*pf_t)(char*);
//int main()
//{
//	void (*pf)(char*) = test;
//	pf_t pf2 = &test;
//
//	return 0;
//}

//void (*signal(int, void(*)(int)))(int);//简化前
//typedef void(*pf_t)(int);//类型重命名
//pf_t signal2(int, pf_t);//简化后

typedef int* ptr_t;
#define PTR_T int*
int main()
{
	//ptr_t p1;//p1是整型指针
	//PTR_T p2;//p2是整型指针

	ptr_t p1, p2;//p1,p2是整型指针
	PTR_T p3, p4;//p3是整型指针,p4是整型
	//int *p3,p4； *只和p3组合

	return 0;
}